package com.javasea.netty.har.client.netty;

import com.javasea.netty.har.common.endec.CustomProtobufDecoder;
import com.javasea.netty.har.common.endec.CustomProtobufEncoder;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.TimeUnit;

/**
 * @ClassName: ClientChannelInitializer
 * @Author: longxiaonan@163.com
 * @Date: 2018/8/1 12:37
 * @Description:
 */
public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {

    /**
     * 客户端连接代码
     */
    private String nioClientCode;
    private String host;
    private int port;

    public ClientChannelInitializer(String nioClientCode, String host, int port) {
        this.nioClientCode = nioClientCode;
        this.host = host;
        this.port = port;
    }

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        // proto自定义编码解码器 https://www.cnblogs.com/Binhua-Liu/p/5577622.html
        // ProtobufVarint32LengthFieldPrepender：因为ProtobufEncoder只是将message的各个filed按照规则输出了，并没有serializedSize，所以socket无法判定package（封包）。这个Encoder的作用就是在ProtobufEncoder生成的字节数组前，prepender一个varint32数字，表示serializedSize。
        // ProtobufVarint32FrameDecoder：这个decoder和Prepender做的工作正好对应，作用就是“成帧”，根据seriaziedSize读取足额的字节数组--一个完整的package。
        pipeline.addLast(new ProtobufVarint32FrameDecoder());
        pipeline.addLast("decoder",new CustomProtobufDecoder());
        pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
        pipeline.addLast("encoder",new CustomProtobufEncoder());

        //心跳检测
        pipeline.addLast(new IdleStateHandler(0,5,0,TimeUnit.SECONDS));
        //客户端的逻辑
        pipeline.addLast("handler", new PrinterClientHandler());
    }
}
